package tech.yunjing.train.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tech.yunjing.train.entity.Account;
import tech.yunjing.train.entity.RedPacket;
import tech.yunjing.train.entity.SmallRedPacket;
import tech.yunjing.train.service.AccountService;
import tech.yunjing.train.service.LoginRedisService;
import tech.yunjing.train.service.exception.*;
import tech.yunjing.train.util.JsonResult;
import tech.yunjing.train.util.PasswordUtil;
import tech.yunjing.train.util.Utility;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 将RedPacketServiceimp 和SmallRedPacketService中的数据集中处理
 * 避免在contoller类中产生大量代码。
 * Created by 刘飞 on 2017-6-8.
 */
@Service
public class ServiceImp {
    //红包的接口实现类
    @Autowired
    private RedPacketServiceImp redPacketService;

    @Autowired
    private SmallRedPacketServiceimp<SmallRedPacket> smallRedPacketServiceimp;
    @Autowired
    private LoginRedisService loginRedisService;
    @Autowired
    private AccountService accountService;
    /**
     * 根据红包名称 红包金额 红包数量 在mymql中增加对应的红包数据
     * 然后调用Utility工具类中的方法随机生成小红包的金额并存储在map中
     * 其中小红包的id为1到红包数量  value为红包金额
     * 并将其key做为redis数据库中的key  value做为redis数据库中小红包对象的金额
     * 失败时异常  成功时返回map
     * @param redPacketName
     * @param smallRedPacketNumber
     * @param redPacketAmount
     * @return
     */
    public JsonResult<RedPacket> addRedPage(String redPacketName, Integer smallRedPacketNumber, Double redPacketAmount, String userAccount, String passWord)throws RedPacketAmountException,SmallRedPacketNumberException,RedPacketNameException {
        if(passWord==null||passWord.trim().isEmpty()){
            throw new PaymentPasswordException("支付密码不能为空");
        }
        if(redPacketName==null||redPacketName.trim().isEmpty()){
            throw new RedPacketNameException("红包名称不能为空");
        }
        if(userAccount==null||userAccount.trim().isEmpty()){
            throw new UserLoginException("用户账户不能为空");
        }
        if(redPacketAmount==null){
            throw new RedPacketAmountException("请输入正确的红包金额");
        }
        if(smallRedPacketNumber==null){
            throw new SmallRedPacketNumberException("请输入正确的小红包数量");
        }
        //根据userAccount判断用户是否登陆
        Object userInfo=loginRedisService.getUserAccountKey(userAccount);
        if(userInfo==null){
            throw new UserLoginException("请先登录");
        }
        //查找用户账户信息
        Account account=accountService.findByAccountName(userAccount);
        if(account==null){
            throw new AccountNotFoundException("账户不存在");
        }
        //将用户密码和用户输入密码作比较
        if(!account.getPaymentPassword().equals(PasswordUtil.md5(passWord))){
            throw new PaymentPasswordException("支付密码错误，请确认输入");
        }
        //判断用户余额能否发红包
        if(account.getAccountBalance()<redPacketAmount){
            throw new AccountBalanceException("支付余额不足");
        }
        //调用红包增加的方法 在mysql中增加红包 插入其红包名 红包金额 小红包数量 用户账户
        redPacketService.addRedPacket(redPacketName, redPacketAmount, smallRedPacketNumber,userAccount);
        //根据红包金额 红包数量 随机分配小红包存在Map中
        Map<Integer,Double> map= Utility.getSmallRedPacket(redPacketAmount,smallRedPacketNumber);
        //将小红包保存在redis中
        saveSmallRedPacket(redPacketName+userAccount,map);
        //在用户余额中减去红包金额
        accountService.updateBalanceByAccountName(account.getAccountBalance()-redPacketAmount,userAccount);
        //返回map
        return new JsonResult(map);

    }


    /**
     * 据红包名称 红包金额 红包数量 在mymql中修改对应的红包数据
     * 并根据红包名称删除redis中的小红包
     * 根据修改后的数据 从新获取map并添加到redis中
     * @param redPacketName
     * @param smallRedPacketNumber
     * @param redPacketAmount
     * @return
     */
    public JsonResult upDatePage(String redPacketName, Integer smallRedPacketNumber, Double redPacketAmount, String userAccount, String passWord) throws RedPacketAmountException, SmallRedPacketNumberException, RedPacketNameException {

        if(redPacketName==null||redPacketName.trim().isEmpty()){
            throw new RedPacketNameException("红包名称不能为空");
        }
        if(userAccount==null||userAccount.trim().isEmpty()){
            throw new UserLoginException("用户账户不能为空");
        }
        if(redPacketAmount==null){
            throw new RedPacketAmountException("请输入正确的红包金额");
        }
        if(smallRedPacketNumber==null){
            throw new SmallRedPacketNumberException("请输入正确的小红包数量");
        }
        if(passWord==null||passWord.trim().isEmpty()){
            throw new PaymentPasswordException("支付密码不能为空");
        }
        //根据userAccount判断用户是否登陆
        Object userInfo=loginRedisService.getUserAccountKey(userAccount);
        if(userInfo==null){
            throw new UserLoginException("请先登录");
        }
        //查找用户账户信息
        Account account=accountService.findByAccountName(userAccount);
        if(account==null){
            throw new AccountNotFoundException("账户不存在");
        }
        //将用户密码和用户输入密码作比较
        if(!account.getPaymentPassword().equals(PasswordUtil.md5(passWord))){
            throw new PaymentPasswordException("支付密码错误，请确认输入");
        }
        //找到redis数据库中所有的小红包
        List<SmallRedPacket> list= smallRedPacketServiceimp.findall(redPacketName+userAccount);
        //获取修改前红包的金额
        double total= Utility.getTotal(list);
        //判断用户余额能否发红包
        if(account.getAccountBalance()+total<redPacketAmount){
            throw new AccountBalanceException("支付余额不足");
        }
        //在数据库中修改大红包数量 金额  userAcount和红包名是为了查找红包
        redPacketService.updateRedPacket(redPacketName,smallRedPacketNumber,redPacketAmount,userAccount);
        //在redis中删除原有的小红包
        smallRedPacketServiceimp.deleteall(redPacketName+userAccount);
        //根据红包金额和红包数量随机分配小红包
        Map<Integer,Double> map= Utility.getSmallRedPacket(redPacketAmount,smallRedPacketNumber);
        //将新的小红包保存在redis数据库中
        saveSmallRedPacket(redPacketName+userAccount,map);
        //将数据库中的账户余额修改
        accountService.updateBalanceByAccountName(account.getAccountBalance()-redPacketAmount+total,userAccount);
        return new JsonResult(map);
    }

    /**
     * 根据红包名称修改大红包状态 小红包状态 并返回剩余的钱数
     * @param redPacketName
     * @return
     */
    public JsonResult removeRedPacket(String redPacketName, String userAccount, String passWord){
        if(redPacketName==null||redPacketName.trim().isEmpty()){
            throw new RedPacketNameException("红包名称不能为空");
        }
        if(userAccount==null||userAccount.trim().isEmpty()){
            throw new UserLoginException("用户账户不能为空");
        }
        if(passWord==null||passWord.trim().isEmpty()){
            throw new PaymentPasswordException("支付密码不能为空");
        }
        //根据userAccount判断用户是否登陆
        Object userInfo=loginRedisService.getUserAccountKey(userAccount);
        if(userInfo==null){
            throw new UserLoginException("请先登录");
        }
        //查找用户账户信息
        Account account=accountService.findByAccountName(userAccount);
        if(account==null){
            throw new AccountNotFoundException("账户不存在");
        }
        //将用户密码和用户输入密码作比较
        if(!account.getPaymentPassword().equals(PasswordUtil.md5(passWord))){
            throw new PaymentPasswordException("支付密码错误，请确认输入");
        }
        //逻辑删除原有的红包
        int i= redPacketService.removePacket(redPacketName,userAccount);
        if (i!=1){
            throw new RedPacketDeleteException("删除红包失败");
        }
        //找到redis数据库中所有的小红包
        List<SmallRedPacket> list= smallRedPacketServiceimp.findall(redPacketName+userAccount);
        if(list.isEmpty()){
            throw new SmallRedPacketException("红包名不正确");
        }
        //得到发布状态的小红包的金额的总额
        double total= Utility.getTotal(list);
        //将小红包的状态全部修改为删除状态
        for (SmallRedPacket smallRedPacket:list){
            smallRedPacket.setStatus(2);
            smallRedPacketServiceimp.put(smallRedPacket.getSmallRedPacketId()+"",smallRedPacket,-1L,redPacketName+userAccount);
        }
        accountService.updateBalanceByAccountName(account.getAccountBalance()+total,userAccount);
        return new JsonResult(total);
    }
    public JsonResult findRedPacket(String redPacketName, String userAccount){
        if(redPacketName==null||redPacketName.trim().isEmpty()){
            throw new RedPacketNameException("红包名称不能为空");
        }
        if(userAccount==null||userAccount.trim().isEmpty()){
            throw new UserLoginException("红包账户不能为空");
        }
        //查找数据库中的红包信息
        RedPacket redPacket=redPacketService.findRedPacketByRedPacketName(redPacketName,userAccount);
        //根据红包的名称查找所有的小红包
        List<SmallRedPacket> list= smallRedPacketServiceimp.findall(redPacketName+userAccount);
        //获取所有小红包金钱总数
        double total= Utility.getTotal(list);
        //根据状态获取还没领取的红包
        int smallRedPacketNumber=Utility.getSmallRedPacketNumber(list);
        //修改红包的状态
        redPacket.setRedPacketAmount(total);
        redPacket.setSmallPacketNumber(smallRedPacketNumber);
        //将红包对象返回
        return new JsonResult(redPacket);
    }




    /**
     * 根据红包名称和Map 将其存入到Redis中的方法
     * @param redPacketName
     * @param map
     */
    private void saveSmallRedPacket(String redPacketName,Map<Integer,Double> map){
        //将Map中的Key当作Redis中的key,将SmallRedPacket对象当作value 存入redis中
        for(Map.Entry<Integer,Double> entry:map.entrySet()){
            SmallRedPacket smallRedPacket=new SmallRedPacket();
            smallRedPacket.setSmallRedPacketId(entry.getKey());
            smallRedPacket.setSmallRedPacketAmount(entry.getValue());
            smallRedPacket.setStatus(0);
            smallRedPacket.setCreatDate(new Date());
            smallRedPacketServiceimp.put(entry.getKey()+"",smallRedPacket,-1L,redPacketName);

        };
    }
}
